package modeling.editors;


import java.awt.Frame;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JPanel;

import model.FrameworkModel;
import model.FrameworkTreeContentProvider;
import model.FrameworkTreeLabelProvider;

import org.dom4j.Document;
import org.dom4j.Element;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.*;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.ide.IDE;

import com.wolfram.jlink.MathGraphicsJPanel;

import swing2swt.layout.BorderLayout;
import util.FileUtil;
import util.MathUtil;
import util.ModelToScriptUtil;
import util.XMLUtil;

import app.MConstants;

public class DesignActivityAnalysisPageEditor extends MultiPageEditorPart implements IResourceChangeListener{
	
	private Table table;
	private Table table1;
	Button typesetButton;
	private JPanel jGraphsPanel = null;
	
	String editorFilePath;
	Map<String, String> modelsMap;
	
	//editorCount to flag the count of this class's instances, and when is 0, kill Mathematica's Kernel
	//when instantiate an editor, use <>++
	//when dispose an editor use <>--
	private static int editorCount = 0;
	
	Tree tree;
	/** The text editor used in page 0. */
	private TextEditor editor;

	/**
	 * Creates a multi-page editor example.
	 */
	public DesignActivityAnalysisPageEditor() {
		super();
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
		editorCount++;
	}
	/**
	 * Creates page 0 of the multi-page editor,
	 * which contains a text editor.
	 */
	void createPage0() {
		final Composite compositeMain = new Composite(getContainer(), SWT.NONE);
		compositeMain.setLayout(new BorderLayout(0, 0));

		final Composite composite = new Composite(compositeMain, SWT.NONE);
		composite.setLayoutData(BorderLayout.NORTH);

		final Button loadButton = new Button(composite, SWT.NONE);
		loadButton.setText("Load");
		loadButton.setBounds(0, 0, 44, 23);

		final Button expandButton = new Button(composite, SWT.NONE);
		expandButton.setText("Expand");
		expandButton.setBounds(50, 0, 44, 23);

		final Text text = new Text(composite, SWT.BORDER);
		text.setBounds(105, 2, 200, 21);
		text.setEditable(false);
		final Composite composite_1 = new Composite(compositeMain, SWT.NONE);
		composite_1.setLayout(new FillLayout());
		composite_1.setLayoutData(BorderLayout.CENTER);

		final TreeViewer tv = new TreeViewer(composite_1, SWT.BORDER);
		//创建表头列
		final Tree tree = tv.getTree();
		tree.setLayoutData(new GridData(GridData.FILL_BOTH));
		final TreeColumn tc1 = new TreeColumn(tree, SWT.LEFT);
		tc1.setText("Design Coordination Name");
		tc1.setWidth(300);
		final TreeColumn tc2 = new TreeColumn(tree, SWT.LEFT);
		tc2.setText("Design Coordination Description");
		tc2.setWidth(800);
		tv.setContentProvider(new FrameworkTreeContentProvider());
		tv.setLabelProvider(new FrameworkTreeLabelProvider());
		tree.setHeaderVisible(true);
		tree.setLinesVisible(true);
		String temp = modelsMap.get(MConstants.FRAMEWORK_MODEL);
		if(temp!=null) {
			setTreeInput(tv, temp);
			text.setText(temp);
		}
		loadButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				String frameworkModelPath =FileUtil.getFilePathFromDlg(composite.getShell(), MConstants.XML_FILTER_NAMES, MConstants.XML_FILTER_EXTENSIONS, text.getText().trim(), 0);
				if(frameworkModelPath!=null && !"".equals(frameworkModelPath)) {
					text.setText(frameworkModelPath);
					modelsMap.put(MConstants.FRAMEWORK_MODEL, frameworkModelPath);
					FileUtil.writeObject(modelsMap, editorFilePath);
//					FileUtil.writeProperties(MConstants.FRAMEWORK_MODEL_FILE_PATH, MConstants.FRAMEWORK_MODEL, frameworkModelPath);
					setTreeInput(tv, frameworkModelPath);
			}
		}});
		expandButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				tv.expandToLevel(TreeViewer.ALL_LEVELS);
			}
		});
//		composite.setLayout(new FillLayout());
//		final TreeViewer tv = new TreeViewer(composite, SWT.BORDER);
//		tv.setContentProvider(new FrameworkTreeContentProvider());
//	    tv.setLabelProvider(new FrameworkTreeLabelProvider());
		int index = addPage(compositeMain);
		setPageText(index, MConstants.FRAMEWORK_MODEL);
	}
	protected void setTreeInput(TreeViewer tv, String frameworkModelPath) {
		Document doc = XMLUtil.read(frameworkModelPath);
//		XMLUtil.getFrameworkTree(tree, doc);
		 tv.setAutoExpandLevel(2);
		 tv.setInput(new FrameworkModel(doc).getModel());
	}
	/**
	 * Creates page 1 of the multi-page editor,
	 * which allows you to change the font used in page 2.
	 */
	void createPage1() {

		Composite mainComposite = new Composite(getContainer(), SWT.NONE);
		mainComposite.setLayout(new BorderLayout(0, 0));

		final Composite composite = new Composite(mainComposite, SWT.NONE);
		composite.setLayoutData(BorderLayout.NORTH);

		final Button loadButton = new Button(composite, SWT.NONE);
		loadButton.setText("Load");
		loadButton.setBounds(0, 0, 44, 23);
		final Text text = new Text(composite, SWT.BORDER);
		text.setBounds(55, 2, 200, 21);
		text.setEditable(false);
		loadButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				try {
					String projectModelPath = FileUtil.getFilePathFromDlg(getContainer().getShell(), MConstants.XML_FILTER_NAMES, MConstants.XML_FILTER_EXTENSIONS, text.getText().trim(),0);
					if(projectModelPath!=null && !"".equals(projectModelPath)) {
						text.setText(projectModelPath);
						modelsMap.put(MConstants.PROJECT_MODEL, projectModelPath);
						FileUtil.writeObject(modelsMap, editorFilePath);
//						FileUtil.writeProperties(MConstants.PROJECT_MODEL_FILE_PATH, MConstants.PROJECT_MODEL, projectModelPath);
						handleProjectTableEvent(projectModelPath);
					}
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});

		final Composite composite_1 = new Composite(mainComposite, SWT.NONE);
		composite_1.setLayout(new FillLayout());
		composite_1.setLayoutData(BorderLayout.CENTER);

		table = new Table(composite_1, SWT.CHECK | SWT.FULL_SELECTION | SWT.BORDER |SWT.V_SCROLL | SWT.H_SCROLL);
		table.setLinesVisible(true);
		table.setHeaderVisible(true);

		final TableColumn newColumnTableColumn = new TableColumn(table, SWT.CENTER);
		newColumnTableColumn.setAlignment(SWT.CENTER);
		newColumnTableColumn.setWidth(100);
		newColumnTableColumn.setText("ID");

		final TableColumn newColumnTableColumn_7 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_7.setWidth(260);
		newColumnTableColumn_7.setText("Project Name");

		final TableColumn newColumnTableColumn_1 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_1.setWidth(100);
		newColumnTableColumn_1.setText("Date");

		final TableColumn newColumnTableColumn_2 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_2.setWidth(100);
		newColumnTableColumn_2.setText("Duty");

		final TableColumn newColumnTableColumn_3 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_3.setWidth(100);
		newColumnTableColumn_3.setText("Subordination");

		final TableColumn newColumnTableColumn_6 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_6.setWidth(100);
		newColumnTableColumn_6.setText("Subject Code");

		final TableColumn newColumnTableColumn_5 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_5.setWidth(100);
		newColumnTableColumn_5.setText("Grant NO");

		final TableColumn newColumnTableColumn_4 = new TableColumn(table, SWT.NONE);
		newColumnTableColumn_4.setWidth(100);
		newColumnTableColumn_4.setText("Amout");
		String temp = modelsMap.get(MConstants.PROJECT_MODEL);
		if(temp!=null) {
			handleProjectTableEvent(temp);
			text.setText(temp);
		}
		
		int index = addPage(mainComposite);
		setPageText(index, MConstants.PROJECT_MODEL);
	}
	protected void handleProjectTableEvent(String s) {
		Document doc = XMLUtil.read(s);
		Iterator<Element> pIterator = doc.getRootElement().elementIterator("project");
		XMLUtil.getProjectTable(table, pIterator);
	}
	/**
	 * Creates page 2 of the multi-page editor,
	 * which shows the sorted text.
	 */
	void createPage2() {
		Composite mainComposite = new Composite(getContainer(), SWT.NONE);
		mainComposite.setLayout(new BorderLayout(0, 0));

		final Composite composite = new Composite(mainComposite, SWT.NONE);
		composite.setLayoutData(BorderLayout.NORTH);

		final Button loadButton = new Button(composite, SWT.NONE);
		loadButton.setText("Load");
		loadButton.setBounds(0, 0, 44, 23);
		final Text text = new Text(composite, SWT.BORDER);
		text.setBounds(55, 2, 200, 21);
		text.setEditable(false);
		loadButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				try {
					String methodModelPath = FileUtil.getFilePathFromDlg(getContainer().getShell(), MConstants.XML_FILTER_NAMES, MConstants.XML_FILTER_EXTENSIONS, text.getText().trim(),0);
					if(methodModelPath!=null && !"".equals(methodModelPath)) {
						text.setText(methodModelPath);
						modelsMap.put(MConstants.METHOD_MODEL, methodModelPath);
						FileUtil.writeObject(modelsMap, editorFilePath);
						handleMethodTableEvent(methodModelPath);
					}
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});

		final Composite composite_1 = new Composite(mainComposite, SWT.NONE);
		composite_1.setLayout(new FillLayout());
		composite_1.setLayoutData(BorderLayout.CENTER);

		table1 = new Table(composite_1, SWT.CHECK | SWT.FULL_SELECTION | SWT.BORDER |SWT.V_SCROLL | SWT.H_SCROLL);
		table1.setLinesVisible(true);
		table1.setHeaderVisible(true);
		final TableColumn newColumnTableColumn = new TableColumn(table1, SWT.NONE);
		newColumnTableColumn.setWidth(200);
		newColumnTableColumn.setText("name");

//		final TableColumn newColumnTableColumn_3 = new TableColumn(table1, SWT.NONE);
//		newColumnTableColumn_3.setWidth(61);
//		newColumnTableColumn_3.setText("axis num");
//
//		final TableColumn newColumnTableColumn_4 = new TableColumn(table1, SWT.NONE);
//		newColumnTableColumn_4.setWidth(72);
//		newColumnTableColumn_4.setText("project num");

		final TableColumn newColumnTableColumn_1 = new TableColumn(table1, SWT.NONE);
		newColumnTableColumn_1.setWidth(239);
		newColumnTableColumn_1.setText("description");

		final TableColumn newColumnTableColumn_2 = new TableColumn(table1, SWT.NONE);
		newColumnTableColumn_2.setWidth(229);
		newColumnTableColumn_2.setText("input");
		
		final TableColumn newColumnTableColumn_3 = new TableColumn(table1, SWT.NONE);
		newColumnTableColumn_3.setWidth(61);
		newColumnTableColumn_3.setText("output");

		String temp = modelsMap.get(MConstants.METHOD_MODEL);
		if(temp!=null) {
			handleMethodTableEvent(temp);
			text.setText(temp);
		}
		
		int index = addPage(mainComposite);
		setPageText(index, MConstants.METHOD_MODEL);
	}
	
	protected void handleMethodTableEvent(String s) {
		Document doc = XMLUtil.read(s);
		XMLUtil.getMethodTable(table1, doc);
	}
	void createPage3() {
		Composite mainComposite = new Composite(getContainer(), SWT.NONE);
		
		mainComposite.setLayout(new BorderLayout(0, 0));

		final Composite composite = new Composite(mainComposite, SWT.NONE);
		composite.setLayoutData(BorderLayout.NORTH);

		final Button analysisButton = new Button(composite, SWT.NONE);
		analysisButton.setText("Analysis");
		analysisButton.setBounds(0, 0, 51, 23);
		
		
		typesetButton = new Button(composite, SWT.CHECK);
		typesetButton.setText("TypeSet");
		typesetButton.setBounds(69, 3, 61, 16);

		final Label colNumLabel = new Label(composite, SWT.NONE);
		colNumLabel.setText("Col Num:");
		colNumLabel.setBounds(136, 5, 43, 13);

		final Text text = new Text(composite, SWT.BORDER);
		text.setBounds(185, 2, 30, 17);
		
		analysisButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				analysis(text.getText().trim());
			}
		});
		final Composite composite_1 = new Composite(mainComposite, SWT.EMBEDDED);
		composite_1.setLayout(new FillLayout());
		composite_1.setLayoutData(BorderLayout.CENTER);

		final Frame frame = SWT_AWT.new_Frame(composite_1);
//		frame.setLayout((LayoutManager) new BorderLayout());

		frame.add(getJGraphsPanel());
		
		int index = addPage(mainComposite);
		setPageText(index, "Analysis Result");
	}
	/**
	 * Creates the pages of the multi-page editor.
	 */
	protected void createPages() {
		createPage0();
		createPage1();
		createPage2();
		createPage3();
	}
	/**
	 * The <code>MultiPageEditorPart</code> implementation of this 
	 * <code>IWorkbenchPart</code> method disposes all nested editors.
	 * Subclasses may extend.
	 */
	public void dispose() {
		editorCount--;
		if(editorCount==0)
			MathUtil.killKernelLink();
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
		super.dispose();
	}
	/**
	 * Saves the multi-page editor's document.
	 */
	public void doSave(IProgressMonitor monitor) {
		getEditor(0).doSave(monitor);
	}
	/**
	 * Saves the multi-page editor's document as another file.
	 * Also updates the text for page 0's tab, and updates this multi-page editor's input
	 * to correspond to the nested editor's.
	 */
	public void doSaveAs() {
		IEditorPart editor = getEditor(0);
		editor.doSaveAs();
		setPageText(0, editor.getTitle());
		setInput(editor.getEditorInput());
	}
	/* (non-Javadoc)
	 * Method declared on IEditorPart
	 */
	public void gotoMarker(IMarker marker) {
		setActivePage(0);
		IDE.gotoMarker(getEditor(0), marker);
	}
	/**
	 * The <code>MultiPageEditorExample</code> implementation of this method
	 * checks that the input is an instance of <code>IFileEditorInput</code>.
	 */
	public void init(IEditorSite site, IEditorInput editorInput)
		throws PartInitException {
		
		String editorFilePathPart1 = Platform.getInstanceLocation().getURL().getPath();
		String editorFilePathPart2 = ((IFileEditorInput)editorInput).getFile().getFullPath().toString();
		editorFilePath = editorFilePathPart1 + editorFilePathPart2;
		
//		System.out.println(file.getAbsolutePath());
//		IFile file = ((IFileEditorInput)editorInput).getFile();
		if (!(editorInput instanceof IFileEditorInput))
			throw new PartInitException("Invalid Input: Must be IFileEditorInput");
		super.init(site, editorInput);
		modelsMap = (HashMap)FileUtil.readObject(editorFilePath);
		if(modelsMap == null)
			modelsMap = new HashMap<String, String>();
		this.setTitle(editorInput.getName());
	}
	/* (non-Javadoc)
	 * Method declared on IEditorPart.
	 */
	public boolean isSaveAsAllowed() {
		return true;
	}
	/**
	 * Closes all project files on project close.
	 */
	public void resourceChanged(final IResourceChangeEvent event){
		if(event.getType() == IResourceChangeEvent.PRE_CLOSE){
			Display.getDefault().asyncExec(new Runnable(){
				public void run(){
					IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
					for (int i = 0; i<pages.length; i++){
						if(((FileEditorInput)editor.getEditorInput()).getFile().getProject().equals(event.getResource())){
							IEditorPart editorPart = pages[i].findEditor(editor.getEditorInput());
							pages[i].closeEditor(editorPart,true);
						}
					}
				}            
			});
		}
	}
	private JPanel getJGraphsPanel() {
		if (jGraphsPanel == null) {
			jGraphsPanel = new MathGraphicsJPanel(MathUtil.getKernelLink());
//			jGraphsPanel.setLayout((LayoutManager) new BorderLayout());
			jGraphsPanel.setBorder(BorderFactory
					.createTitledBorder(""));
		}
		return jGraphsPanel;
	}
	protected void analysis(String colNum) {
		//read model path from file
		String mathScript = ModelToScriptUtil.getFrameworkModeAndProjectModelScript(modelsMap) + ";\n" +ModelToScriptUtil.getMethodModelScript(modelsMap, colNum);
		System.out.println(mathScript);
		//operate mathematica kernel
//		MathUtil.getKernelLink();
		((MathGraphicsJPanel)getJGraphsPanel()).setImageType(
				typesetButton.getSelection() ? MathGraphicsJPanel.TYPESET : MathGraphicsJPanel.GRAPHICS);
//				false ? MathGraphicsJPanel.TYPESET : MathGraphicsJPanel.GRAPHICS);
		((MathGraphicsJPanel) getJGraphsPanel())
				.setMathCommand(mathScript.trim());
	}
}
